package com.bjpower.services.impl;


import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bjpower.common.constants.Sysconts;
import com.bjpower.common.enums.SysCode;
import com.bjpower.common.exceptions.type.SysException;
import com.bjpower.domain.PmsMenu;
import com.bjpower.domain.PmsOperator;
import com.bjpower.mapper.PmsMenuMapper;
import com.bjpower.mapper.PmsOperatorMapper;
import com.bjpower.models.dto.OperatorLoginDto;
import com.bjpower.models.meuns.MenuItem;
import com.bjpower.models.meuns.SubMenu;
import com.bjpower.models.request.OperatorLoginRequest;
import com.bjpower.services.OperatorLoginService;
import com.bjpower.utlis.JwtUtils;
import com.bjpower.utlis.RedisHelper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class OperatorLoginServiceImpl implements OperatorLoginService {

    private Object lockObject = new Object();

    @Resource
    private PmsOperatorMapper pmsOperatorMapper;

    @Resource
    private PmsMenuMapper pmsMenuMapper;

    @Resource
    private RedisHelper redisHelper;
    @Override
    public OperatorLoginDto loginService(OperatorLoginRequest loginRequest){

        //获取登录信息判断用户是否存在
        String loginName = loginRequest.getLoginName();

        PmsOperator pmsOperator = pmsOperatorMapper.selectOne(new LambdaQueryWrapper<PmsOperator>()
                .eq(PmsOperator::getLoginName, loginName));
        if (pmsOperator == null){
            //创建自定义异常处理类 返回异常数据给前端
            throw new SysException(SysCode.OPERATOR_LOGIN_NAME_ERROR);
        }
        //获取用户登录状态是否可用
        String status = pmsOperator.getStatus();
        if (!(status.equals("ENABLE"))){
            throw new SysException(SysCode.OPERATOR_DISABLED_ERROR);
        }

        //获取salt
        String salt = pmsOperator.getSalt();

        String  pwd = DigestUtil.md5Hex(loginRequest.getLoginPwd()+salt);
        if (!pwd.equals(pmsOperator.getLoginPwd())){
            throw new SysException(SysCode.OPERATOR_LOGIN_PWD_ERROR);
        }

        //创建jwt
        String token = JwtUtils.createJwt(pmsOperator.getId().toString(), 60*60*24*7);
        //使用模板方法将用户信息以及jwt存入redis
        String jwtKey = Sysconts.OPERATOR_JWT_KEY + pmsOperator.getId();
        HashMap<String, String> map = new HashMap<>();
        map.put("jwt",token);
        map.put("type",pmsOperator.getType());
        map.put("loginTime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        redisHelper.setHashAll(jwtKey,map,60*60*24*7);
        return new OperatorLoginDto(pmsOperator.getShowName(),pmsOperator.getId(), token);
    }

    /**
     * 优化后的获取菜单方法 从redis中获取
     * @param operatorId
     * @return
     */
    @Override
    public List<SubMenu> getMenusByOperatorId(Long operatorId) {
        List<SubMenu> subMenuList = new ArrayList<>();
        //从redis中获取菜单信息
        try {
            String key = Sysconts.OPERATOR_MENU_KEY + operatorId;
            String val = redisHelper.getVal(key);
            if (StrUtil.isNotBlank(val)){
                //将redis中的数据转换成List<SubMenu>
                return JSONUtil.toList(val, SubMenu.class);
            }
            synchronized (lockObject){
                subMenuList = getMenus(operatorId);
                //将数据存入redis中
                redisHelper.setVal(Sysconts.OPERATOR_MENU_KEY + operatorId, JSONUtil.toJsonStr(subMenuList));
            }
        }catch (Exception e){
            e.printStackTrace();
            subMenuList = getMenus(operatorId);
        }

        return  subMenuList;
    }

    //创建获取菜单方法
    private List<SubMenu> getMenus(Long operatorId) {
        List<SubMenu> subMenuList = new ArrayList<>();
        //根据id查询出所有菜单
        List<PmsMenu> menuList = pmsMenuMapper.selectMenusList(operatorId);
        //循环便利每个菜单对象
        for (PmsMenu mu : menuList){
            //将所有菜单对象封装成SubMenu对象
            SubMenu subMenu = new SubMenu();
            subMenu.setId(mu.getId());
            subMenu.setName(mu.getName());
            subMenu.setUrl(mu.getUrl());
            subMenu.setNumber(mu.getNumber());

            List<MenuItem> menuItemList = new ArrayList<>();
            //查询出所有子菜单
            List<PmsMenu> childMenuList = pmsMenuMapper.selectMenuChildrenList(mu.getId());
            //便利所以集合放入到SubMenu对象中
            for (PmsMenu childMenu : childMenuList){
                SubMenu menu = new SubMenu();
                menu.setId(childMenu.getId());
                menu.setName(childMenu.getName());
                menu.setUrl(childMenu.getUrl());
                menu.setNumber(childMenu.getNumber());
                menuItemList.add(menu);
            }
            subMenu.setItemList(menuItemList);
            subMenuList.add(subMenu);
        }
        return subMenuList;
    }

}
